<?php
/**
 * 周舟 hzboye010@163.com
 * addby sublime snippets
 * 微信支付入口
 */

namespace Api\Controller;

use Shop\Api\OrdersApi;
use Shop\Api\WxpayNotifyApi;
use Shop\Api\OrderRefundMoneyApi;
use Common\Api\ExchangeLogApi;
use Common\Api\PayOrderApi;
use Admin\Api\ConfigApi;
use Admin\Api\OrdersPaycodeApi;
// use Think\Controller;
use Api\Controller\WxpayController;

class WxpayAppController extends WxpayController{
  
  const REFUND = 'Api/WxpayApp/refundSubmit';

		protected $config = array();
	  /**
     * 构造函数
     */
    public function __construct(){
      parent::__construct();
      $this->getWxpayConfig();
    }

    // public function test(){
    //   // dump($this->config);exit;
    // }
    //微信退款查询
    public function refundQuery($out_trade_no){
      //TODO
    }

    //微信申请退款
    public function refundSubmit(){//20160421741461226214
      //Admin/OrdersController/refund 过来
      // dump($r);exit;
      //参考 AlipayRefundController/submit
      /**************************请求参数**************************/
      header('content-type:text/html;charset=utf8');
      // echo $n.'...';
      $batch_no = I('WIDbatch_no');
      // echo '--'.$batch_no.'--';exit;
      $detail   = I('WIDdetail_data');
      $r = apiCall(OrderRefundMoneyApi::GET_INFO,array(array('batch_no'=>$batch_no)));
      // dump($r);//exit;
      // echo M()->getLastSql();exit;
      $rfee = floatval($r['info']['money'])*100; //退款金额
      $order_code = $r['info']['order_code'];
      if(!$r['status'] || !$r['info']) exit($this->getTpl('此单未申请售后呀'));
      if(!$order_code) exit($this->getTpl('此单退款未通过'));
      $r = apiCall(OrdersApi::GET_INFO,array(array('order_code'=>$order_code)));
      // echo M()->getLastSql();
      // dump($r);exit;
      if(!$r['status'] || !$r['info']['pay_code']) exit($this->getTpl('查无此单'));
      if($r['status'] && $r['info']['pay_status']==2)  exit($this->getTpl("此单已退过款"));
      $fee = floatval($r['info']['price'])*100; //订单金额

      /************************************************************/
      //构造要请求的参数数组，无需改动
      $array = array(
        'appid' => $this->config['appid'],
        'mch_id'=> $this->config['mch_id'],
        'nonce_str'=> $this->getRandChar(32),//随机字符串，不长于32位。
        'op_user_id'=>$this->config['mch_id'],//操作员帐号, 默认为商户号
        'out_trade_no'=>$r['info']['pay_code'], //商户订单号 或 微信交易号transaction_id
        'out_refund_no'=>$batch_no, //'退款单号'
        'total_fee' =>$fee,//订单总金额，单位为分
        'refund_fee'=>$rfee,//退款总金额，单位为分
        'op_user_id'=>$this->config['mch_id'],//操作员帐号, 默认为商户号
      );

      $sign = $this->getSign($array);
      $array['sign'] = $sign;//添加签名
      // echo '1------------------<br/>';
      // dump($array);
      // 
      $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
      $xml = $this->arrayToXml($array);

      $path = getcwd().'/Application/Api/Vendor/Wxpay/';//APP_PATH.
      // $path = dirname(dirname(__FILE__)).'/Vendor/Wxpay/'; 
      // $path = dirname(__FILE__).'/../Vendor/Wxpay/';
      // echo $path;//必须绝对路径
      // exit;
      $ch = curl_init();
      curl_setopt($ch,CURLOPT_URL,$url);
      curl_setopt($ch,CURLOPT_HEADER,1);
      curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
      //================
      curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,1); //$curl
      curl_setopt($ch,CURLOPT_SSLCERTTYPE,'pem');
      curl_setopt($ch,CURLOPT_SSLCERT, $path.'apiclient_cert.pem');
      curl_setopt($ch,CURLOPT_SSLKEYTYPE,'pem');
      curl_setopt($ch,CURLOPT_SSLKEY,$path.'apiclient_key.pem');
      // curl_setopt($ch,CURLOPT_SSLKEYTYPE,'pem');
      // curl_setopt($ch,CURLOPT_CAINFO,$path.'rootca.pem');
      //================
      curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
      curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//严格校验2
      curl_setopt($ch,CURLOPT_POST,1);
      curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
      //建立请求
      $data = curl_exec($ch);
      if($data){
        curl_close($ch);
        //清楚 微信XML垃圾头
        $pos = stripos($data,'<xml');
        $data = substr($data,$pos);
        $data = $this->xmlstr_to_array($data);
        // dump($data);
        //=========================
        if($data['return_code'] == 'FAIL') exit($this->getTpl('微信后台:'.$data['return_msg']));
        if($data['result_code'] == 'FAIL') exit($this->getTpl('微信后台:'.$data['err_code_des']));
        // echo '2------------------<br/>';
        // dump($data);
        // exit;
        // if($this->checkSign($data)){
        //TODO  bug 对不上
        //签名验证成功 
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // echo 'refundSubmit get wxdata <br/>';
            $out_trade_no = $data['out_trade_no'];
            //微信支付订单号
            // $trade_no = $data['transaction_id'];
            //交易状态
            $trade_status = $data['result_code'];
            if($data['return_code'] != 'SUCCESS'){
              exit($this->getTpl($data['return_msg']));
            }
            if($data['result_code'] != 'SUCCESS'){
              exit($this->getTpl('出错了'.$data['err_code'].':'.$data['err_code_des'].'!<br/>请重试或联系管理员！'));
            }
            //注释打开 ：每个订单只退款一次
            //注释关闭 ：每个订单可分次退款
            // $r = apiCall(OrdersApi::GET_INFO,array(array('pay_code'=>$out_trade_no)));
            // if($r['status'] && $r['info']){
            // $order_code=$r['info']['order_code'];
            // $r = apiCall(OrderRefundMoneyApi::GET_INFO,array(array('order_code'=>$order_Code)));
              //已退款 直接返回SUCCESS
              // if($r['status'] && !$r['info'])
              //   exit($this->getTpl("向微信后台申请退款成功，请等待微信后台处理 .. "));
            // }
            $this->refundSuccess($batch_no,$detail,$data);
            exit($this->getTpl("向微信后台申请退款成功，请等待微信后台处理 ..."));   //请不要修改或删除

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // } else {
            //验证失败
            // echo '签名失败';
            //调试用，写文本函数记录程序运行情况是否正常
            //logResult("这里写入想要调试的代码变量值，或其他运行的结果记录");
        // }
        //=================
      }else{
        $error = curl_errno($ch);
        echo $this->getTpl("curl出错,错误码: $error");
        curl_close($ch);
      }
    }
    protected function getTpl($con){
      return '<center><h1>'.$con.'</h1></center>';
    }
    //微信退款成功
    public function refundSuccess($batch_no,$detail,$wxdata){
      // echo $batch_no.'='.$detail.'<br/>';
      // dump($wxdata);
      apiCall(OrderRefundMoneyApi::WXREFUND_SUCCESS,array($batch_no,$detail,$wxdata));
    }

    //微信支付回掉
    public function return_url(){
      $result = array();
      $streamData = isset($GLOBALS['HTTP_RAW_POST_DATA'])? $GLOBALS['HTTP_RAW_POST_DATA'] : 'NULL';
      $data = $this->xmlstr_to_array($streamData);
        // addLog('','get data',json_encode($data),'wxapp');
      if($this->checkSign($data)) {
        //签名验证成功
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            $out_trade_no = $data['out_trade_no'];
            //微信支付订单号
            
            $paytype = substr($out_trade_no,0,1);
            if($paytype == 'S'){
              //积分商品的直接处理，注意：未作重复判断
              $this->paySuccess($out_trade_no);
              $result['return_code'] = "SUCCESS";
              exit($this->arrayToXml($result));
            }

            $trade_no = $data['transaction_id'];
            //交易状态
            $trade_status = $data['result_code'];
            // $f = 'fu =';
            // addLog('','',$f.' before log','wxapp');
            if ($trade_status == 'SUCCESS') {
                $r = apiCall(OrdersApi::GET_INFO,array(array('pay_code'=>$out_trade_no)));;
                if($r['status'] && intval($r['info']['pay_status'])>0){
                  //重复判断：已经处理 直接返回SUCCESS
                  // addLog('','',$f.' add log','wxapp');
                  $result['return_code'] = "SUCCESS";
                  exit($this->arrayToXml($result));
                }
                //做过处理
                // addLog('','',$f.' before log :'.json_encode($data),'wxapp');
                $this->log($data);
                // addLog('','',$f.' after log :'.$out_trade_no,'wxapp');
                $this->paySuccess($out_trade_no);
            }
        //——请根据您的业务逻辑来编写程序（以上代码仅作参考）——

            $result['return_code'] = "SUCCESS";   //请不要修改或删除

        //     /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        } else {
            // addLog('','',$sign.'sign error','wxapp');
            //验证失败
            $result['return_code'] = "FAIL";
            $result['return_msg']  = '签名失败';
            //调试用，写文本函数记录程序运行情况是否正常
            //logResult("这里写入想要调试的代码变量值，或其他运行的结果记录");
        }
        echo $this->arrayToXml($result);
    }

    public function checkSign($data){
      $sign = $data['sign'];
      // echo $sign.'--';
      // echo $this->getSign($data).'--';
      unset($data['sign']);
      // echo $this->getSign($data).'--';
      return $sign == $this->getSign($data);
    }

    public function paySuccess($out_trade_no){
        $prex = substr($out_trade_no,0,1);
        // addLog('','before pay success'.$out_trade_no,'','wxapp');
        if($prex == 'T'){
          apiCall(PayOrderApi::SUCCESS,array($out_trade_no,2));
        }elseif($prex=='S'){
          apiCall(ExchangeLogApi::PAYBACK,array($out_trade_no));
        }
        // addLog('','pay success','wxapp');
    }

    public function log($data){
      $entity = array(
        'sign'           => $data['sign'],
        'openid'         => $data['openid'],
        'trade_type'     => $data['trade_type'],
        'bank_type'      => $data['bank_type'],
        'total_fee'      => $data['total_fee'],
        'cash_fee'       => $data['cash_fee'],
        'transaction_id' => $data['transaction_id'],
        'out_trade_no'   => $data['out_trade_no'],
        'time_end'       => $data['time_end'],
        'extra'          => '[微信支付]',
      );
      // addLog('','',json_encode($entity),'wxapp-NotifyApi');
      $result = apiCall(WxpayNotifyApi::ADD,array($entity));
      if(!$result['status']){
          LogRecord($result['info'],__FILE__.__LINE__);
      }

    }
    /**
    * 预支付订单 ，返还app ================== unuse
    * @param  string $id         [description]
    * @return [type]             [description]
    */
    public function pay($code=0){
      // $this->setConfig(C('WXPAY_CONFIG'));
      // if(!$id || !intval($id)) $this->apiReturnErr('错误订单号');
      $p_pos = strpos($code,"P");
      $pay_id = substr($code,$p_pos+1,strlen($code)-$p_pos);
      $result = apiCall(OrdersPaycodeApi::GET_INFO,array(array('id'=>$pay_id)));
      if($result['status'] && is_array($result['info'])){
        $orderCodeArray=explode(';',$result['info']['order_content']);
      }else{
        $this->apiReturnErr('查无此单');
      }
      $order_code = $orderCodeArray[0];

      //查询订单
      $result = apiCall(OrdersApi::GET_INFO,array(array('order_code'=>$order_code)));
      if(!$result['status']){
         LogRecord($result['info'],__FILE__.__LINE__);
      }
      // dump($result);exit;
      $order_info = $result['info'];
      if(is_null($order_info)){
         $this->apiReturnErr('无此订单');
      }
      if($order_info['pay_status'] >0){
        $this->apiReturnErr('订单已付款或退款');
      }
      // dump($order_info);exit;
      $tade_no   = $order_info['order_code'];//pay_code
      $orderBody = $order_info['note']? $order_info['note']:$tade_no;
      $total_fee = $order_info['price']*100; //订单总金额，单位为分
      // echo $total_fee;exit;
      $r = $this->getPrePayOrder($orderBody, $tade_no, $total_fee);
      // dump($r);exit;
      if($r['return_code'] == 'FAIL'){
       $this->apiReturnErr($r['return_msg']);
      }elseif($r['return_code'] == 'SUCCESS'){
       if($r['result_code'] == 'SUCCESS'){
         $this->apiReturnSuc($this->getOrder($r['prepay_id']));
       }else{
         $this->apiReturnErr($r['err_code_des']);
       }
      }else{
       $this->apiReturnErr('返回错误');
      }
    }
    /**
     * 从数据库中取得微信配置信息
     */
    protected function getWxpayConfig() {
        // $config = S('global_config');
        //dump($config);
        // if ($config === false) {
            $map = array('name'=>'WXPAY_CONFIG');
            $fields = 'type,name,value';
            $result = apiCall(ConfigApi::GET_INFO, array($map, false, $fields));
            if ($result['status']) {
              $value = $result['info'];
              $this->config = $this -> parse($value['type'], $value['value']);

            } else {
                LogRecord('INFO:' . $result['info'], '[FILE] ' . __FILE__ . ' [LINE] ' . __LINE__);
                $this -> error($result['info']);
            }
        // }
        // C($config);
    }

    /**
     * 根据配置类型解析配置
     * @param  integer $type 配置类型
     * @param  string $value 配置值
     * @return array|string
     */
    private static function parse($type, $value) {
      switch ($type) {
        case 3 :
          //解析数组
          $array = preg_split('/[,;\r\n]+/', trim($value, ",;\r\n"));
          if (strpos($value, ':')) {
            $value = array();
            foreach ($array as $val) {
              list($k, $v) = explode(':', $val,2);
              $value[$k] = $v;
            }
          } else {
            $value = $array;
          }
          break;
      }
      return $value;
    }
}